package com.mgl.movesprite.game.model;

import java.util.ArrayList;

import org.andengine.engine.camera.Camera;
import org.andengine.engine.camera.hud.HUD;
import org.andengine.entity.scene.Scene;

import com.mgl.movesprite.BuildPanel;
import com.mgl.movesprite.EntityLevelBase;
import com.mgl.movesprite.EntitySpriteLevelBase;
import com.mgl.movesprite.IEntityLevel;
import com.mgl.movesprite.PauseButton;
import com.mgl.movesprite.game.factory.GameObjectFactory;
import com.mgl.movesprite.game.factory.GameType;
import com.mgl.util.Path;
import com.mgl.util.Point;

public class Level extends EntityLevelBase {

	private ArrayList<IEntityLevel> spritesOnSceneList = null;

	private ArrayList<IEntityLevel> spritesToAdd = null;
	private ArrayList<IEntityLevel> spritesToRemove = null;

	// game atts
	private Scene scene = null;
	private Camera camera = null;
	private Background background = null;
	private HUD hud = null;
	private BuildPanel buildPanel = null;

	// level atts
	private Path path = null;

	public Level(Scene scene, Camera camera, GameObjectFactory gameObjectFactory) {

		super(gameObjectFactory);

		this.scene = scene;
		this.camera = camera;

		buildPanel = new BuildPanel(this);
		
		background = (Background) gameObjectFactory.createObject(
				GameType.BACKGROUND_LEVEL1, camera.getWidth() / 2,
				camera.getHeight() / 2);

		scene.attachChild(background);

		spritesOnSceneList = new ArrayList<IEntityLevel>();
		spritesToRemove = new ArrayList<IEntityLevel>();
		spritesToAdd = new ArrayList<IEntityLevel>();

		initHUD();

	}

	private void initHUD() {
		try {

			PauseButton pauseButton = new PauseButton(camera.getWidth() - 50, 50,
					gameObjectFactory.getGameTextureManager()
							.getPauseButtonTexture(), gameObjectFactory
							.getGameTextureManager()
							.getVertexBufferObjectManager(), gameObjectFactory,
					scene, camera);

			hud = new HUD();
			hud.attachChild(pauseButton);
			hud.registerTouchArea(pauseButton);
			camera.setHUD(hud);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void addEntity(IEntityLevel entityLevelBase) {
		try {

			spritesToAdd.add(entityLevelBase);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void removeEntity(IEntityLevel entityLevelBase) {

		try {

			spritesToRemove.add(entityLevelBase);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void init() {
		try {

			initializePathList();
			initializeLevel();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void update(float pSecondsElapsed, Level level) {
		try {
	
			updateSpritesOnScene(pSecondsElapsed, level);
	
			addSpritesToScene(pSecondsElapsed, level);
	
			removeSpritesFromScene(pSecondsElapsed, level);
	
		} catch (Exception e) {
			e.printStackTrace();
		}
	
	}

	private void initializeLevel() {
		try {

			BeginPoint beginPoint = (BeginPoint) gameObjectFactory
					.createObject(GameType.BEGIN_POINT, 30, 30);
			beginPoint.init(path);

			EndPoint endPoint = (EndPoint) gameObjectFactory.createObject(
					GameType.END_POINT, 460, 700);

			BuildZone buildZone = (BuildZone) gameObjectFactory.createObject(
					GameType.BUILD_ZONE, 400, 400);

			// attaching childs
			// ----------------------------------------------------------
			addEntity(beginPoint);
			addEntity(endPoint);
			addEntity(buildZone);

			// registering touch areas
			// ---------------------------------------------------
			scene.registerTouchArea(buildZone);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void initializePathList() {
		try {

			path = new Path();

			path.push(new Point(310, 87));
			path.push(new Point(360, 150));
			path.push(new Point(300, 171));
			path.push(new Point(81, 243));
			path.push(new Point(60, 315));
			path.push(new Point(105, 393));
			path.push(new Point(328, 444));
			path.push(new Point(361, 483));
			path.push(new Point(341, 520));
			path.push(new Point(57, 600));
			path.push(new Point(25, 658));
			path.push(new Point(70, 712));
			path.push(new Point(468, 738));

			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void removeSpritesFromScene(float pSecondsElapsed, Level level) {
		try {

			for (IEntityLevel el : spritesToRemove) {
				spritesOnSceneList.remove(el);
			}

			spritesToRemove = new ArrayList<IEntityLevel>();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void addSpritesToScene(float pSecondsElapsed, Level level) {
		try {

			for (IEntityLevel el : spritesToAdd) {
				el.detachFromScene(scene);
				el.attachToScene(scene);
				spritesOnSceneList.add(el);

			}
			spritesToAdd = new ArrayList<IEntityLevel>();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void updateSpritesOnScene(float pSecondsElapsed, Level level) {
		try {

			for (IEntityLevel s : spritesOnSceneList) {
				s.update(pSecondsElapsed, level);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void showBuildPanel(ArrayList<GameType> typeBuildList, EntitySpriteLevelBase buildPlace) {
		try {
			
			buildPanel.show(typeBuildList,buildPlace);
			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public ArrayList<IEntityLevel> getSpritesOnSceneList() {
		return spritesOnSceneList;
	}

	public void setSpritesOnSceneList(ArrayList<IEntityLevel> spritesOnSceneList) {
		this.spritesOnSceneList = spritesOnSceneList;
	}

	public Scene getScene() {
		return scene;
	}

	public void setScene(Scene scene) {
		this.scene = scene;
	}

	public Path getPath() {
		return path;
	}

	public void setPath(Path path) {
		this.path = path;
	}

	public ArrayList<IEntityLevel> getSpritesToAdd() {
		return spritesToAdd;
	}

	public void setSpritesToAdd(ArrayList<IEntityLevel> spritesToAdd) {
		this.spritesToAdd = spritesToAdd;
	}

	public ArrayList<IEntityLevel> getSpritesToRemove() {
		return spritesToRemove;
	}

	public void setSpritesToRemove(ArrayList<IEntityLevel> spritesToRemove) {
		this.spritesToRemove = spritesToRemove;
	}

	public Background getBackground() {
		return background;
	}

	public void setBackground(Background background) {
		this.background = background;
	}

	public Camera getCamera() {
		return camera;
	}

	public void setCamera(Camera camera) {
		this.camera = camera;
	}

	public HUD getHud() {
		return hud;
	}

	public void setHud(HUD hud) {
		this.hud = hud;
	}

	public BuildPanel getBuildPanel() {
		return buildPanel;
	}

	public void setBuildPanel(BuildPanel buildPanel) {
		this.buildPanel = buildPanel;
	}

}
